package za.co.trojanc.ini_lib;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A class representing configuration read from a ini file.
 * @author Charl Thiem
 * @since 09 Sep 2009
 */
public class INIConfig{

	/** Mapping of sections contained in this configuration */
	private Map<String, INISection> sections;
	/** List of section names, used to keep track of section indices */
	private List<String> sectionNames;
	
	/**
	 * Creates a new instance of <code>INIConfig</code>.
	 */
	public INIConfig() {
		this.sections  = new HashMap<String, INISection>();
		this.sectionNames = new ArrayList<String>();
	}
	
	/**
	 * Gets a section with the specified name.
	 * @param sectionName Name of the section
	 * @return The section in the ini file.
	 */
	public INISection getSection(String sectionName) {
		return this.sections.get(sectionName);
	}
	
	
	/**
	 * Removes a section from this configuration
	 * @param sectionName Name of section to remove.
	 * @return The section that was removed.
	 */
	public INISection removeSection(String sectionName) {
		return this.sections.remove(sectionName);
	}
	
	/**
	 * Returns true if this config contains a section with the specified name.
	 * @param sectionName Name of section to search for.
	 * @return True if section exists.
	 */
	public boolean containsSectionNamed(String sectionName) {
		return this.sectionNames.contains(sectionName);
	}
	
	/**
	 * Adds a section to this configuration.
	 * @param section Section to add to this configuration.
	 * @return Section that was added to this configuration.
	 */
	public INISection addSection (INISection section) {
		if (this.containsSectionNamed(section.getName())) {
			return null;
		}
		this.sectionNames.add(section.getName());
		this.sections.put(section.getName(), section);
		return section;
	}
	
	/**
	 * Creates a new section and adds it to this configuration.
	 * @param sectionName Name of the section to create.
	 * @return Reference to the section that was created.
	 */
	public INISection createSection(String sectionName) {
		return this.addSection(new INISection(sectionName));
	}
	
	/**
	 * Gets a array of section names in the order they are defined.
	 * @return String array of section names.
	 */
	public String[] getSectionNames() {
		return this.sectionNames.toArray(new String[0]);
	}
	
	/**
	 * Returns an array of INISections in the order they are defined
	 * @return
	 */
	public INISection[] getSections() {
		List<INISection> secs = new ArrayList<INISection>();
		String[] names = this.getSectionNames();
		for (String n : names) {
			secs.add(this.getSection(n));
		}
		return secs.toArray(new INISection[0]);
	}
	
	/**
	 * Gets an String field from the configuration.
	 * @param config Configuration to retrieve it from.
	 * @param sectionName Name of section
	 * @param fieldName Name of the field to get
	 * @param defaultValue Default value if field could not be found.
	 * @return
	 */
	public String getStringField(final String sectionName, final String fieldName, final String defaultValue){
		INISection section = this.getSection(sectionName);
		if (section == null){
			return defaultValue;
		}
		return section.getStringValue(fieldName, defaultValue);
	}
	
	/**
	 * Gets a Boolean field from the configuration
	 * @param sectionName Name of the section to get the value from.
	 * @param fieldName Name of the field to get the value from/
	 * @param defaultValue Default value if the value is not found.
	 * @return The boolean value of the field.
	 */
	public Boolean getBooleanField(final String sectionName, final String fieldName, final Boolean defaultValue){
		INISection section = this.getSection(sectionName);
		if (section == null){
			return defaultValue;
		}
		return section.getBooleanValue(fieldName, defaultValue);
	}
	
	/**
	 * Gets an integer field from the configuration
	 * @param sectionName Name of section
	 * @param fieldName Name of the field to get
	 * @param defaultValue Default value if field could not be found.
	 * @return
	 */
	public int getIntField(final String sectionName, final String fieldName, final int defaultValue){
		INISection section = this.getSection(sectionName);
		if (section == null){
			return defaultValue;
		}
		return section.getIntValue(fieldName, defaultValue);
	}
	
	public INIField[] getListFields(final String sectionName, final String fieldName){
		INISection section = this.getSection(sectionName);
		if (section != null){
			return section.getListFields(fieldName);
		}
		return new INIField[0];
	}
}
